/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Engine2D;

import Engine2D.entity.Player;
import Engine2D.gui.GLTextConsole;
import Engine2D.camera.Camera;
import Engine2D.camera.FollowCamera;
import Engine2D.graphics.font.GLFont;
import Engine2D.graphics.particle.GLParticleSystem;
import Engine2D.level.Level;
import Engine2D.engine.Engine;
import Engine2D.geometry.Polygon;
import Engine2D.geometry.Rectangle;
import Engine2D.geometry.Shape;
import Engine2D.geometry.Transform;
import Engine2D.graphics.GLColour;
import Engine2D.graphics.GLImage;
import Engine2D.graphics.GLSpriteSheet;
import Engine2D.gui.BasicComponent;
import Engine2D.gui.MessageBox;
import Engine2D.gui.MessageBox2;
import Engine2D.input.InputHandler;
import Engine2D.input.KeyListener;
import Engine2D.input.MouseListener;
import Engine2D.level.tile.TileManager;
import Engine2D.math.Matrix3f;
import Engine2D.renderer.ShapeRenderer;
import java.awt.Canvas;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Random;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.GL11;
import sun.misc.GC;

/**
 *
 * @author Garys
 */
public class Game extends Canvas implements MouseListener, KeyListener {

    /**
     *
     */
    protected final Random random = new Random();
    private Engine engine = null;
    private InputHandler input = new InputHandler();
    private Level levels[] = new Level[1];
    private Level level;
    private Player player;
    private Camera currentCamera;
    /**
     *
     */
    public static int WIDTH = 800;
    /**
     *
     */
    public static int HEIGHT = 600;
    /**
     *
     */
    public boolean isFullScreen = false;
    private GLFont font = null;
    private GLTextConsole console = null;
    private boolean consoleToggle = false;
    private String name = "Tile Engine 0.0.1.1";
    private String renderMessage = "";
    private String gemsLeft = "";
    private String winMessage = "You Win!!";
    private GLSpriteSheet spriteSheet;
    private MessageBox message;
    private MessageBox2 message2;
    private ShapeRenderer shapeRenderer;
    private Shape rect, rect2, rect3, poly1, poly2;

    /**
     *
     */
    public Game() {
        engine = Engine.getInstance();
        engine.init(WIDTH, HEIGHT, isFullScreen, this, name);
        engine.start();
    }

    /**
     *
     * @param args
     */
    public static void main(String[] args) {

        new Game();
    }

    /**
     *
     */
    public void init() {

        input.init(HEIGHT);

        levels = new Level[1];
        levels[0] = new Level(1000, 1000, 0, null, input);
        level = levels[0];

        player = new Player(this, input, "Gary");

        player.findStartPos(level);


        spriteSheet = GLSpriteSheet.getInstance();


        currentCamera = new FollowCamera(player, input, level);

        level.add(player);

        input.addMouseListener(this);
        input.addKeyListener(this);

        font = new GLFont("resources/fonts/tahoma.png", 0);
        console = new GLTextConsole(font, 30, new GLColour(1f, 1f, 1f, 0.2f), GLColour.BLACK);

        message = new MessageBox(50, 50, 110, 30, null, new Rectangle(0f, 0f, 110f, 30f), "Click Me", GLColour.GREEN, font);
        message2 = new MessageBox2(200, 50, 110, 30, null, new Rectangle(0f, 0f, 110f, 30f), "Double Click me", GLColour.GREEN, font);


        input.addKeyListener(message);
        input.addMouseListener(message);

        input.addKeyListener(message2);
        input.addMouseListener(message2);


        shapeRenderer = new ShapeRenderer();
//         rect = new Rectangle(50, 50, 100, 60);
//         rect2 = new Rectangle(80, 90, 40, 200);
//         rect3 = new Rectangle(400, 50, 100, 400);

        //poly1 = new Polygon(new float[]{40,50,42,23,234,233,493,780,24,56});
        //poly2 = new Polygon();
        //((Polygon)poly2).setClosed(false);

    }

    /**
     *
     */
    public void render() {

        bindSpriteSheet();
        level.renderBackground(this, currentCamera.xScroll, currentCamera.yScroll);

        level.renderParticles(currentCamera.xScroll, currentCamera.yScroll);
        level.renderSprites(this, currentCamera.xScroll, currentCamera.yScroll);

        renderGUI();


        shapeRenderer.draw(message.shape);
        shapeRenderer.draw(message2.shape);
        //shapeRenderer.draw(rect2);
        //shapeRenderer.draw(rect3);
        //shapeRenderer.draw(poly1);
        //shapeRenderer.draw(poly2);

    }

    /**
     *
     * @param ticks
     */
    public void tick(int ticks) {
        input.poll(WIDTH, HEIGHT);
        level.tick(ticks);
        currentCamera.tick();

        if (input.isKeyPressed(Keyboard.KEY_GRAVE)) {
            consoleToggle = !consoleToggle;
        }


        if (ticks == 1) {
            renderMessage = "Ticks:" + engine.ticks + " Fps:" + engine.frames;
            gemsLeft = "Gems left:" + (level.gemCount - player.gemsCollected) + " Gems Collected:" + player.gemsCollected;
            console.addLine(renderMessage, GLColour.BLACK);
        }


    }

    /**
     *
     */
    public void onEngineClose() {
    }

    private void renderGUI() {


        font.print(player.name, (player.x - currentCamera.xScroll) - 5, (player.y - currentCamera.yScroll) - 15, 1, GLColour.WHITE);
        font.print("Player x: " + player.x + " Player Y: " + player.y, WIDTH - 300, HEIGHT - 33, 1, GLColour.WHITE);
        message.render(0, 0);
        message2.render(0, 0);
        font.print(renderMessage, 10, 10, 1, GLColour.WHITE);

        if (consoleToggle) {
            console.draw(20, 10, 10, 1, true);
        }

        font.print(gemsLeft, WIDTH - 300, HEIGHT - 20, 1, GLColour.WHITE);


        if (level.gemCount - player.gemsCollected == 0) {
            font.print(winMessage, (WIDTH / 2) / 2, (HEIGHT / 2) - 30, 5, GLColour.WHITE);
        }
    }

    private void bindSpriteSheet() {

        spriteSheet.bind();
    }

    /**
     *
     * @param mouseButton
     * @param pressedX
     * @param pressedY
     */
    @Override
    public void mousePressed(int mouseButton, int pressedX, int pressedY) {
    }

    /**
     *
     * @param mouseButton
     * @param releasedX
     * @param releasedY
     */
    @Override
    public void mouseReleased(int mouseButton, int releasedX, int releasedY) {
    }

    /**
     *
     * @param x
     * @param y
     * @param newX
     * @param newY
     */
    @Override
    public void mouseDragged(int x, int y, int newX, int newY) {
        //((Polygon)poly2).addPoint(newX, 600-newY);
    }

    /**
     *
     * @param x
     * @param y
     * @param newX
     * @param newY
     */
    @Override
    public void mouseMoved(int x, int y, int newX, int newY) {
    }

    /**
     *
     * @param eventButton
     * @param pressedX
     * @param pressedY
     * @param clickCount
     */
    @Override
    public void mouseClicked(int eventButton, int pressedX, int pressedY, int clickCount) {
        if (clickCount >= 2) {
            level.addParticleSystem(new GLParticleSystem(currentCamera.xScroll + pressedX, currentCamera.yScroll + pressedY, 10000, 10000l, 1000l, 10f, -10f, 0f, GLColour.WHITE, "rock"));
        }



    }

    /**
     *
     * @param wheelValue
     */
    @Override
    public void mouseWheelMoved(int wheelValue) {
//        if (wheelValue>0) {
//          ((Polygon)poly2).transform2(new Transform(new float[]{1.000f,0f,0f,0f,1.000f,0f}));
//          
//        } else {
//        ((Polygon)poly2).transform3(new Transform(new float[]{1.000f,0f,0f,0f,1.000f, 0f}));
//        }
    }

    /**
     *
     * @param inputHandler
     */
    @Override
    public void setInputHandler(InputHandler inputHandler) {
    }

    /**
     *
     * @return
     */
    @Override
    public boolean isAcceptingInput() {
        return true;
    }

    /**
     *
     */
    @Override
    public void inputEnded() {
    }

    @Override
    public void inputStarted() {
    }

    /**
     *
     * @param key
     * @param c
     */
    @Override
    public void keyPressed(int key, char c) {

        if (c == 'm') {
            levels[0] = new Level(100, 100, 0, null, input);
            level = levels[0];
            player.findStartPos(level);
            level.add(player);
        }
        if (c == 's') {
            try {
                level.saveToDisk();
            } catch (FileNotFoundException ex) {
                Logger.getLogger(Game.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
            } catch (IOException ex) {
                Logger.getLogger(Game.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
            }
        }

        if (c == 'l') {
            try {
                level.loadFromDisk();
            } catch (FileNotFoundException ex) {
                Logger.getLogger(Game.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
            } catch (IOException ex) {
                Logger.getLogger(Game.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
            } catch (ClassNotFoundException ex) {
                Logger.getLogger(Game.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
            }
            player.findStartPos(level);
            level.add(player);
        }

        if (c == 'd') {
            level.doubleSize();
            System.out.println(level.tiles.length);
            System.out.println(level.h);
            player.y = (level.h * 32);
            currentCamera.tick();
        }

        if (c == 'i') {


            engine.running = false;
            int w = level.w;
            int h = level.h;
            int chunks = w * h;
            
            level.entitiesInTiles = null;
            level.data = null;

            int chunkWidth, chunkHeight;
            int type;
//
//
//
//
//            File water = new File("C:/Users/gary.morris/Documents/SVN/Engine2D/Engine2D/resources/images/Tiles/water.png");
//            File grass = new File("C:/Users/gary.morris/Documents/SVN/Engine2D/Engine2D/resources/images/Tiles/grass.png");
//            File sand = new File("C:/Users/gary.morris/Documents/SVN/Engine2D/Engine2D/resources/images/Tiles/sand.png");
//            File rock = new File("C:/Users/gary.morris/Documents/SVN/Engine2D/Engine2D/resources/images/Tiles/rock.png");
//            File bedRock = new File("C:/Users/gary.morris/Documents/SVN/Engine2D/Engine2D/resources/images/Tiles/bedRock.png");
//
//            //BufferedImage[] buffImages = new BufferedImage[chunks];
//            for (int y = 0; y < h; y++) {
//                BufferedImage[] buffImages = new BufferedImage[w];
//                for (int x = 0; x < w; x++) {
//                    int i = x + y * w;
//                    if (level.tiles[i] == TileManager.water.id) {
//                        try {
//                            buffImages[x] = ImageIO.read(water);
//                        } catch (IOException ex) {
//                            Logger.getLogger(Game.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
//                        }
//                    }
//                    if (level.tiles[i] == TileManager.grass.id) {
//                        try {
//                            buffImages[x] = ImageIO.read(grass);
//                        } catch (IOException ex) {
//                            Logger.getLogger(Game.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
//                        }
//                    }
//                    if (level.tiles[i] == TileManager.rock.id) {
//                        try {
//                            buffImages[x] = ImageIO.read(rock);
//                        } catch (IOException ex) {
//                            Logger.getLogger(Game.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
//                        }
//                    }
//
//                }
//
//                type = 5;
//                chunkWidth = 32;
//                chunkHeight = 32;
//
//                //Initializing the final image  
//                BufferedImage finalImg = new BufferedImage(chunkWidth * w, chunkHeight, type);
//
//                int num = 0;
//                for (int i = 0; i < 1; i++) {
//                    for (int j = 0; j < w; j++) {
//                        finalImg.createGraphics().drawImage(buffImages[num], chunkWidth * j, chunkHeight * i, null);
//                        num++;
//                    }
//                }
//
//// create a file to write the image to (make sure it exists), then use the ImageIO class
//// to write the RenderedImage to disk as a PNG file.
//                File file = new File("C:/Users/gary.morris/Documents/SVN/Engine2D/Engine2D/resources/images/maps/outputMap" + y + ".png");
//                try {
//                    file.createNewFile();
//                } catch (IOException ex) {
//                    Logger.getLogger(Game.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
//                }
//                try {
//                    ImageIO.write(finalImg, "png", file);
//                } catch (IOException ex) {
//                    Logger.getLogger(Game.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
//                }
//
//
//            }

            File[] imgFiles = new File[h];
            for (int i = 0; i < h; i++) {
                imgFiles[i] = new File("C:/Users/gary.morris/Documents/SVN/Engine2D/Engine2D/resources/images/maps/outputMap" + i + ".png");
            }

//            BufferedImage[] buffImages = new BufferedImage[chunks];
//            for (int i = 0; i < h; i++) {
//                try {
//                    buffImages[i] = ImageIO.read(imgFiles[i]);
//                } catch (IOException ex) {
//                    Logger.getLogger(Game.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
//                }
//            }
            
            
            
            type = 5;
            chunkWidth = 3200;
            chunkHeight = 32;

            //Initializing the final image  
            BufferedImage finalImg = new BufferedImage(chunkWidth, chunkHeight * h, type);

            int num = 0;
            for (int i = 0; i < h; i++) {
                for (int j = 0; j < 1; j++) {
                    try {
                        finalImg.createGraphics().drawImage(ImageIO.read(imgFiles[i]), chunkWidth * j, chunkHeight * i, null);
                    } catch (IOException ex) {
                        Logger.getLogger(Game.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
                    }
                    num++;
                }
            }

            // create a file to write the image to (make sure it exists), then use the ImageIO class
            // to write the RenderedImage to disk as a PNG file.
            File file = new File("C:/Users/gary.morris/Documents/SVN/Engine2D/Engine2D/resources/images/maps/final.png");
            try {
                file.createNewFile();
            } catch (IOException ex) {
                Logger.getLogger(Game.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
            }
            try {
                ImageIO.write(finalImg, "png", file);
            } catch (IOException ex) {
                Logger.getLogger(Game.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
            }
            
            
//            for (File file1 : imgFiles) {
//                file1.delete();
//            }

        }







    }

    /**
     *
     * @param key
     * @param c
     */
    @Override
    public void keyReleased(int key, char c) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
}
